import React, { Component } from "react";
import { Button, Card, Grid, Icon, Tree, Loader } from "@scuf/common";
import {
  Alert,
  Modal,
  Input,
  InputNumber,
  SelectPicker,
  Form,
  Schema,
} from "rsuite";
import { v4 as uuidv4 } from "uuid";
import { Menu, Item, contextMenu } from "react-contexify";

import http from "../../../components/http/http";
import rest from "../../../assets/rest";
import Graphic from "../../../components/graphic/component-list";
import CustomField from "../../../components/common/customField";

import GraphicCss from "./graphic.module.css";

class GraphicEdit extends Component {
  constructor(props) {
    super(props);
    let id = this.props.match.params.locationId;
    let locationArr = id.split("_");
    this.state = {
      id: id,
      locationId: locationArr[locationArr.length - 1],
      view: { open: false },
      bindValue: { open: false },
      checkViewModel: this.checkViewLogic(),
      components: [],
      equipments: [],
      points: [],
      views: [],
      width: "calc(100% - 2rem)",
      height: "calc(100% - 1rem)",
      viewForm: {
        state: "",
        id: "",
        name: "",
        width: "",
        height: "",
        active: "",
      },
      activeViewId: 0,
      loadingView: true,
      loadingItem: false,
      viewTitle: "Please choose a view",
      currentBindingForm: {
        equipment: "",
        point: "",
        text: "",
      },
      modules: [],
      graphicComponents: [],
      componentList: [],
      currentUuid: "",
      menuId: "pxview_edit_menu",
      currentPerms: [],
    };
    this.handleSaveView = this.handleSaveView.bind(this);
    this.handleAddView = this.handleAddView.bind(this);
    this.handleBindingValue = this.handleBindingValue.bind(this);
    this.handleSaveViewItem = this.handleSaveViewItem.bind(this);
    this.handleBindingValueMenu = this.handleBindingValueMenu.bind(this);
    this.handleDeleteMenu = this.handleDeleteMenu.bind(this);
    this.handleChooseComponent = this.handleChooseComponent.bind(this);
    this.handleContextMenu = this.handleContextMenu.bind(this);
    this.handleViewClick = this.handleViewClick.bind(this);
    this.handleEditView = this.handleEditView.bind(this);
    this.handleDeleteView = this.handleDeleteView.bind(this);
    this.loadModules = this.loadModules.bind(this);
    this.loadEquipments = this.loadEquipments.bind(this);
    this.loadPoints = this.loadPoints.bind(this);
    this.loadViews = this.loadViews.bind(this);
    this.graphicList = this.graphicList.bind(this);
    this.addComponent = this.addComponent.bind(this);
  }

  UNSAFE_componentWillMount() {
    let menus = window.localStorage.getItem(rest.menus);
    if (!!menus) {
      this.setState({
        currentPerms: JSON.parse(menus).filter((x) => x.name === "Workbench")[0]
          .perms,
      });
    }
    this.loadModules();
    this.loadViews();
    this.loadEquipments();
  }

  componentWillUnmount() {
    this.setState = (state, callback) => {
      return;
    };
  }

  loadModules() {
    http.get(rest.pxview.components).then((response) => {
      if (response.status === 200 && response.data.code === 200) {
        let arr = response.data.data.map((x) => {
          return {
            value: x.id,
            label: x.name,
          };
        });
        this.setState({ modules: arr, graphicComponents: response.data.data });
      }
    });
  }

  //加载所有view信息，左侧菜单栏
  loadViews() {
    const { locationId } = this.state;
    http
      .get(rest.pxview.pxviews, {
        params: {
          locationId: locationId,
        },
      })
      .then((response) => {
        if (response.status === 200) {
          this.setState({ views: response.data.data, loadingView: false });
        }
      });
  }

  //加载所有equipment信息
  loadEquipments() {
    const { locationId } = this.state;
    http
      .get(rest.pxview.equipments, {
        params: {
          locationId: locationId,
        },
      })
      .then((response) => {
        if (response.status === 200 && response.data.code === 200) {
          if (!!response.data.data) {
            let result = response.data.data.map((res) => {
              let obj = {};
              obj.value = res.equipmentId;
              obj.label = res.equipmentName;
              obj.points = res.points.map((x) => {
                return {
                  value: x.pointId,
                  label: x.pointName,
                };
              });
              return obj;
            });
            this.setState({ equipments: result });
          }
        }
      });
  }

  //加载所有equipment信息
  loadPoints(equipmentId) {
    const { currentBindingForm, equipments } = this.state;
    let obj = equipments.filter(
      (equipment) => Number(equipment.value) === Number(equipmentId)
    )[0].points;
    this.setState({
      currentBindingForm: {
        ...currentBindingForm,
        equipment: equipmentId,
      },
      points: obj,
    });
  }

  checkViewLogic() {
    const { StringType, NumberType } = Schema.Types;
    return Schema.Model({
      name: StringType().isRequired("This field is required."),
      width: NumberType().isRequired("This field is required."),
      height: NumberType().isRequired("This field is required."),
    });
  }

  //在画板中添加一个组件
  addComponent(obj) {
    const { components, activeViewId } = this.state;
    let id = uuidv4();
    let component = obj.item({
      id: id,
      drag: true,
      box: this.refs.box,
      graphicId: obj.graphicId,
      width: obj.width,
      height: obj.height,
      path: obj.path,
      type: obj.type,
      text: "",
      editable: obj.editable,
    });
    if (activeViewId === 0) {
      Alert.error("Please choose a view");
      return;
    }
    components.push(component);
    this.setState({ components: components });
  }

  //点击一个view加载所有内容
  handleViewClick(obj) {
    const { id, name } = obj;
    this.setState({
      activeViewId: id,
      viewTitle: `Edit: ${name}`,
      loadingItem: true,
    });
    http
      .get(rest.pxview.detail, {
        params: {
          id: id,
        },
      })
      .then((response) => {
        if (response.status === 200 && response.data.code === 200) {
          this.setState({ components: [] });
          let data = response.data.data;
          let width = data.width;
          let height = data.height;
          let components = data.items.map((res) => {
            return Graphic.componentList({
              id: res.uuid,
              drag: true,
              box: this.refs.box,
              width: res.layoutWidth,
              height: res.layoutHeight,
              graphicId: res.componentId,
              top: res.layoutTop,
              left: res.layoutLeft,
              text: res.text,
              type: res.type,
              imagePaths: res.imagePaths,
              path: res.defaultImagePath,
              point: !!res.point ? res.point.id : null,
              editable: res.editable,
            });
          });
          this.setState({
            width: `${width}px`,
            height: `${height}px`,
            components: components,
            loadingItem: false,
          });
          Alert.success("load success!");
        } else {
          this.setState({ loadingItem: false });
          Alert.error("load failed!");
        }
      })
      .catch((error) => {
        this.setState({ loadingItem: false });
        Alert.error("load failed!");
      });
  }

  //保存view中的item
  handleSaveViewItem() {
    const { components, activeViewId } = this.state;
    if (activeViewId === 0) {
      Alert.error("please choose a view!");
      return;
    }
    let items = !!components.length
      ? components.map((component) => {
          let dom = document.getElementById(component.props.id);
          let obj = {};
          obj.top = dom.offsetTop;
          obj.left = dom.offsetLeft;
          obj.width = dom.clientWidth;
          obj.height = dom.clientHeight;
          obj.componentId = component.props.graphicId;
          obj.viewId = activeViewId;
          obj.uuid = component.props.id;
          obj.text = component.props.text;
          obj.editable = component.props.editable;
          obj.pointId = component.props.point;
          return obj;
        })
      : [];
    let result = {
      id: activeViewId,
      items: items,
    };
    http
      .post(rest.pxview.items, result)
      .then((response) => {
        if (response.status === 200 && response.data.code === 200) {
          Alert.success("Save Success!");
        } else {
          Alert.error("Save failed");
        }
      })
      .catch((error) => {
        Alert.error("Save failed");
      });
  }

  //保存一个view，有id编辑，没有id新增
  handleSaveView() {
    const { viewForm, locationId } = this.state;
    const { viewCheckForm } = this.refs;
    if (!viewCheckForm.check()) {
      return;
    }
    let callback = (response) => {
      if (response.status === 200 && response.data.code === 200) {
        Alert.success("Success!");
        this.setState({ view: { open: false } });
        this.loadViews();
      } else if (response.data.code === 400) {
        Alert.error("view name is already exist!");
      }
    };
    if (!!viewForm.id) {
      http
        .put(rest.pxview.pxviews, {
          id: viewForm.id,
          name: viewForm.name,
          width: viewForm.width,
          height: viewForm.height,
          active: viewForm.active,
          locationId: locationId,
        })
        .then(callback)
        .catch((error) => {
          Alert.error("Error!");
        });
    } else {
      http
        .post(rest.pxview.pxviews, {
          name: viewForm.name,
          width: viewForm.width,
          height: viewForm.height,
          locationId: locationId,
        })
        .then(callback)
        .catch((error) => {
          Alert.error("Error!");
        });
    }
  }

  //点击添加一个view的处理过程
  handleAddView() {
    const {
      offsetWidth: originWidth,
      offsetHeight: originHeight,
    } = this.refs.box;
    this.setState(
      {
        width: "calc(100% - 2rem)",
        height: "calc(100% - 1rem)",
      },
      () => {
        const { offsetWidth, offsetHeight } = this.refs.box;
        this.setState({
          width: originWidth,
          height: originHeight,
          view: { open: true },
          viewForm: {
            ...this.state.viewForm,
            id: "",
            name: "",
            state: "Add New View",
            width: offsetWidth,
            height: offsetHeight,
          },
        });
      }
    );
  }

  //点击编辑一个view的处理过程
  handleEditView(obj) {
    const { viewForm } = this.state;
    const { id, name, width, height, active } = obj;
    this.setState({
      viewForm: {
        ...viewForm,
        state: `Edit ${name}`,
        id: id,
        name: name,
        width: width,
        height: height,
        active: active,
      },
      view: { open: true },
    });
  }

  //点击删除一个view的处理过程
  handleDeleteView(obj) {
    const { id } = obj;
    http
      .delete(rest.pxview.pxviews, {
        params: {
          id: id,
        },
      })
      .then((response) => {
        if (response.status === 200 && response.data.code === 200) {
          Alert.success("delete success!");
          this.loadViews();
        }
      });
  }

  //处理绑点对象方法
  handleBindingValue() {
    const { currentUuid, currentBindingForm, components } = this.state;
    let newComponents = components.map((component) => {
      let obj = {
        ...component.props,
      };
      if (component.key === currentUuid) {
        obj.text = currentBindingForm.text;
        obj.point = currentBindingForm.point;
      }
      return Graphic.componentList(obj);
    });
    this.setState({
      currentBindingForm: { equipment: "", point: "", text: "" },
      components: newComponents,
      bindValue: { open: false },
    });
  }

  handleChooseComponent(e) {
    const { components } = this.state;
    let id = e.target.getAttribute("id");
    let arr = components.map((component) => component.key);
    arr.forEach((id) => {
      let { style } = document.getElementById(id);
      if (!!style.outline) {
        style.outline = "none";
      }
    });
    if (id !== "box") {
      e.target.style.outline = "dotted dodgerblue 0.13rem";
    }
  }

  //右键菜单
  handleContextMenu(event) {
    event.preventDefault();
    const { menuId } = this.state;
    let id = event.target.getAttribute("id");
    if (id !== "box") {
      contextMenu.show({
        id: menuId,
        event: event,
      });
      this.setState({
        currentUuid: id,
      });
    }
  }

  //右键菜单绑点事件
  handleBindingValueMenu() {
    const { currentUuid, components, equipments } = this.state;
    let dom = document.getElementById(currentUuid);
    let editable = dom.getAttribute("editable");
    if (Number(editable) === 0) {
      Alert.warning("this component can not bind value");
      return;
    }
    let component = components.filter(
      (component) => component.key === currentUuid
    )[0];
    let equipment = equipments.filter((equipment) => {
      let pointArr = equipment.points.filter(
        (point) => point.value === component.props.point
      );
      if (!!pointArr && pointArr.length !== 0) {
        return pointArr[0].value === component.props.point;
      }
      return false;
    });
    if (!!equipment && equipment.length !== 0) {
      this.setState(
        {
          bindValue: { open: true },
          show: false,
          points: equipment[0].points,
        },
        () => {
          this.setState({
            currentBindingForm: {
              equipment: equipment[0].value,
              point: component.props.point,
              text: component.props.text,
            },
          });
        }
      );
    } else {
      this.setState({
        bindValue: { open: true },
        show: false,
      });
    }
  }

  //右键菜单删除事件
  handleDeleteMenu() {
    const { currentUuid, components } = this.state;
    let arr = components.filter((component) => component.key !== currentUuid);
    this.setState({ components: arr, show: false });
  }

  //graphic组件递归
  graphicList(components) {
    if (components.length === 0) {
      return;
    }
    return components.map((data) => {
      if (!!data.children && data.children.length > 0) {
        return (
          <Tree.Content.Item key={data.id} title={data.name}>
            {this.graphicList(data.children)}
          </Tree.Content.Item>
        );
      } else {
        return (
          <Tree.Content.Item
            key={data.id}
            title={data.name}
            icon={<Icon name="paperclip" size="small" color="blue" />}
            onTitleClick={() => {
              this.addComponent({
                item: Graphic.componentList,
                path: data.path,
                graphicId: data.id,
                width: data.width,
                height: data.height,
                type: data.typeId,
                editable: data.editable,
              });
            }}
          />
        );
      }
    });
  }

  render() {
    const {
      id,
      views,
      viewForm,
      checkViewModel,
      activeViewId,
      loadingView,
      loadingItem,
      viewTitle,
      components,
      componentList,
      modules,
      menuId,
      graphicComponents,
      currentPerms,
      currentBindingForm,
    } = this.state;
    return (
      <Grid className="fixOuterHeight">
        <Grid.Row>
          <Grid.Column width={2}>
            <Grid.Row>
              <Grid.Column className={GraphicCss.halfHeight} width={12}>
                <Card style={{ height: "100%" }}>
                  <Card.Header title="Graphics">
                    {currentPerms.indexOf("workbench:graphic:edit") !== -1 ? (
                      <Button
                        type="link"
                        onClick={this.handleAddView}
                        content=""
                        size="medium"
                        icon="document-new"
                        iconRoot="common"
                      />
                    ) : null}
                  </Card.Header>
                  <Card.Content>
                    <Tree style={{ width: "100%" }}>
                      <Tree.Content>
                        <Loader loading={loadingView}>
                          {views.map((view) => {
                            return (
                              <Tree.Content.Item
                                key={view.id}
                                title={view.name}
                                active={activeViewId === view.id}
                                onTitleClick={() => {
                                  this.handleViewClick({
                                    id: view.id,
                                    name: view.name,
                                  });
                                }}
                                icon={
                                  <Icon
                                    className={GraphicCss.actionIcon}
                                    name="document"
                                    size="small"
                                    color="blue"
                                  />
                                }
                                actionRenderer={
                                  currentPerms.indexOf(
                                    "workbench:graphic:edit"
                                  ) !== -1 ? (
                                    <div style={{ width: "3rem" }}>
                                      <Icon
                                        className="pointer"
                                        root="building"
                                        flipped="horizontally"
                                        name="edit"
                                        size="medium"
                                        color="green"
                                        onClick={() => {
                                          this.handleEditView({
                                            id: view.id,
                                            name: view.name,
                                            width: view.width,
                                            height: view.height,
                                            active: view.active,
                                          });
                                        }}
                                      />
                                      <Icon
                                        className="pointer"
                                        root="building"
                                        flipped="horizontally"
                                        name="delete"
                                        size="medium"
                                        color="red"
                                        onClick={() => {
                                          this.handleDeleteView({
                                            id: view.id,
                                          });
                                        }}
                                      />
                                    </div>
                                  ) : null
                                }
                              />
                            );
                          })}
                        </Loader>
                      </Tree.Content>
                    </Tree>
                  </Card.Content>
                </Card>
              </Grid.Column>
            </Grid.Row>
            <Grid.Row>
              <Grid.Column className={GraphicCss.halfHeight} width={12}>
                <Card style={{ height: "100%" }}>
                  <Card.Header title="Components" />
                  <Card.Content>
                    <SelectPicker
                      block={true}
                      searchable={false}
                      cleanable={false}
                      onChange={(e) => {
                        this.setState({
                          componentList: graphicComponents.filter(
                            (x) => x.id === e
                          )[0].children,
                        });
                      }}
                      placeholder="Select a Module"
                      data={modules}
                    />
                    <Tree
                      style={{
                        width: "100%",
                        marginTop: "10px",
                      }}
                    >
                      <Tree.Content>
                        {this.graphicList(componentList)}
                      </Tree.Content>
                    </Tree>
                  </Card.Content>
                </Card>
              </Grid.Column>
            </Grid.Row>
          </Grid.Column>
          <Grid.Column width={10}>
            <Card style={{ height: "100%" }}>
              <Card.Header title={viewTitle}>
                <Button
                  onClick={() => {
                    this.props.history.push(`/workbench/graphic-list/${id}`);
                  }}
                  textTransform={false}
                  size="small"
                  type="secondary"
                  content="List"
                />
                {currentPerms.indexOf("workbench:graphic:edit") !== -1 ? (
                  <Button
                    textTransform={false}
                    size="small"
                    type="secondary"
                    content="Save"
                    onClick={this.handleSaveViewItem}
                  />
                ) : null}
                <Button
                  textTransform={false}
                  size="small"
                  type="inline-secondary"
                  content="Clear"
                  onClick={() => this.setState({ components: [] })}
                />
              </Card.Header>
              <Card.Content style={{ width: "100%", height: "100%" }}>
                <div
                  ref="box"
                  id="box"
                  style={{
                    width: this.state.width,
                    height: this.state.height,
                    overflow: "auto",
                    position: "absolute",
                  }}
                  className={`${GraphicCss.grid} ${GraphicCss.gridEdit}`}
                  onContextMenu={this.handleContextMenu}
                  onClick={this.handleChooseComponent}
                >
                  <Loader loading={loadingItem}>{components}</Loader>
                </div>
                <Menu theme="dark" id={menuId}>
                  <Item onClick={this.handleBindingValueMenu}>
                    Binding Value
                  </Item>
                  <Item onClick={this.handleDeleteMenu}>Delete</Item>
                </Menu>
              </Card.Content>
            </Card>
          </Grid.Column>
        </Grid.Row>
        <Modal
          size="sm"
          onHide={() => this.setState({ view: { open: false } })}
          show={this.state.view.open}
          backdrop="static"
        >
          <Modal.Header>{viewForm.state}</Modal.Header>
          <Modal.Body>
            <Form
              fluid
              ref="viewCheckForm"
              onChange={(formValue) => {
                this.setState({ viewForm: formValue });
              }}
              formValue={viewForm}
              model={checkViewModel}
            >
              <CustomField
                name="name"
                label="Name:"
                accepter={Input}
                placeholder="Please input name"
              />
              <CustomField
                name="width"
                label="Width:"
                accepter={InputNumber}
                placeholder="Please input width"
              />
              <CustomField
                name="height"
                label="Height:"
                accepter={InputNumber}
                placeholder="Please input height"
              />
            </Form>
          </Modal.Body>
          <Modal.Footer>
            <Button
              type="secondary"
              size="medium"
              content="Cancel"
              onClick={() => this.setState({ view: { open: false } })}
            />
            <Button
              type="primary"
              size="medium"
              content="Submit"
              onClick={this.handleSaveView}
            />
          </Modal.Footer>
        </Modal>
        <Modal
          size="sm"
          onHide={() => this.setState({ bindValue: { open: false } })}
          show={this.state.bindValue.open}
          backdrop="static"
        >
          <Modal.Header>Edit Properties</Modal.Header>
          <Modal.Body>
            <Form
              fluid
              onChange={(formValue) => {
                this.setState({ currentBindingForm: formValue });
              }}
              formValue={currentBindingForm}
            >
              <CustomField
                name="equipment"
                label="Equipment:"
                block={true}
                searchable={false}
                accepter={SelectPicker}
                onChange={(value) => this.loadPoints(value)}
                data={this.state.equipments}
              />
              <CustomField
                name="point"
                label="Point:"
                block={true}
                searchable={false}
                accepter={SelectPicker}
                data={this.state.points}
              />
              <CustomField
                name="text"
                label="Text:"
                accepter={Input}
                placeholder="Please input your text"
              />
            </Form>
          </Modal.Body>
          <Modal.Footer>
            <Button
              type="secondary"
              size="medium"
              content="Cancel"
              onClick={() =>
                this.setState({
                  currentBindingForm: { point: "", text: "" },
                  bindValue: { open: false },
                })
              }
            />
            <Button
              type="primary"
              size="medium"
              content="Submit"
              onClick={this.handleBindingValue}
            />
          </Modal.Footer>
        </Modal>
      </Grid>
    );
  }
}

export default (props) => (
  <GraphicEdit {...props} key={props.location.pathname} />
);
